import {
  animals,
  celestialStems,
  chineseNumber,
  chineseTen,
  lunarInfo,
  solarMonth,
  solarTerm,
  termInfo,
  terrestrialBranches,
} from './CalendarInfo';

// 传入月日的 offset 传回干支, 0=甲子
function cyclicalm(num: number) {
  return celestialStems[num % 10] + terrestrialBranches[num % 12];
}
// 传入 offset 传回干支, 0=甲子
function cyclical(y: number) {
  const num = y - 1900 + 36;
  return cyclicalm(num);
}

// 返回农历 y年的生肖
function animalsYear(y: number) {
  return animals[(y - 4) % 12];
}

// 返回某年的第n个节气为几日(从0小寒起算)
function sTerm(y: number, n: number) {
  var offDate = new Date(
    31556925974.7 * (y - 1900) +
      termInfo[n] * 60000 +
      Date.UTC(1900, 0, 6, 2, 5),
  );

  return offDate.getUTCDate();
}

// 获取y年的节气
function sTermDate(y: number) {
  const sTermDateArr = [];
  let stdateStr = '';
  let offDate = null;
  for (let i = 0; i < solarTerm.length; i++) {
    offDate = new Date(
      31556925974.7 * (y - 1900) +
        termInfo[i] * 60000 +
        Date.UTC(1900, 0, 6, 2, 5),
    );
    stdateStr =
      (offDate.getMonth() + 1 > 9
        ? offDate.getMonth() + 1
        : '0' + (offDate.getMonth() + 1)) +
      '' +
      (offDate.getUTCDate() > 9
        ? offDate.getUTCDate()
        : '0' + offDate.getUTCDate());
    sTermDateArr.push(stdateStr);
  }
}

// 判断y年的农历中那个月是闰月,不是闰月返回0
function leapMonth(y: number) {
  return lunarInfo[y - 1900] & 0xf;
}

// 返回农历y年m月的总天数
function monthDays(y: number, m: number) {
  return lunarInfo[y - 1900] & (0x10000 >> m) ? 30 : 29;
}

// 返回农历y年闰月的天数
function leapDays(y: number) {
  if (leapMonth(y)) {
    return lunarInfo[y - 1900] & 0x10000 ? 30 : 29;
  } else {
    return 0;
  }
}

//返回农历y年的总天数
function yearDays(y: number) {
  let i,
    sum = 348;

  for (i = 0x8000; i > 0x8; i >>= 1) {
    if (lunarInfo[y - 1900] & i) {
      sum += 1;
    }
  }

  return sum + leapDays(y);
}

// 返回公历y年m+1月的天数

function solarDays(y: number, m: number) {
  if (m == 1) {
    return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 ? 29 : 28;
  } else {
    return solarMonth[m];
  }
}

// 用中文显示农历的日期
function getChinaDay(day: number) {
  const modulo = day % 10;
  const n = modulo == 0 ? 9 : modulo - 1;
  if (day > 31) {
    return '';
  } else if (day == 10) {
    return '初十';
  } else {
    return chineseTen[Math.floor(day / 10)] + chineseNumber[n];
  }
}

let year: number,
  month: number,
  day: number,
  leap: number,
  isLeap: boolean,
  yearCyl: number,
  monCyl: number,
  dayCyl: number,
  hourCyl: number;

// 算出当前月第一天的农历日期和当前农历日期下一个月农历的第一天日期
function Dianaday(objDate: Date) {
  let i,
    temp = 0;

  const baseDate = new Date(1900, 0, 31);

  // 求出和1900年1月31日相差的天数
  let offset = (objDate.getTime() - baseDate.getTime()) / 86400000;

  dayCyl = offset + 40;
  monCyl = 14;
  hourCyl = (objDate.getTime() - baseDate.getTime() + 3300000) / 7200000;

  // 用offset减去每农历年的天数
  // 计算当天是农历第几天
  // i最终结果是农历的年份
  // offset是当年的第几天
  for (i = 1900; i < 2050 && offset > 0; i++) {
    temp = yearDays(i);
    offset -= temp;
    monCyl += 12;
  }

  if (offset < 0) {
    offset += temp;
    i--;
    monCyl -= 12;
  }

  // 农历年份
  year = i;
  yearCyl = i - 1864;

  // 闰哪个月1-12
  leap = leapMonth(i);
  isLeap = false;

  // 用当年的天数offset,逐个减去每月（农历）的天数，求出当天是本月的第几天
  for (i = 1; i < 13 && offset > 0; i++) {
    // 闰月
    if (leap > 0 && i == leap + 1 && !isLeap) {
      --i;
      isLeap = true;
      temp = leapDays(year);
    } else {
      temp = monthDays(year, i);
    }

    offset -= temp;

    // 解除闰月
    if (isLeap && i == leap + 1) {
      isLeap = false;
    }

    if (!isLeap) {
      monCyl++;
    }
  }

  // offset为0时，并且刚才计算的月份是闰月，要校正
  if (offset == 0 && leap > 0 && i == leap + 1) {
    if (isLeap) {
      isLeap = false;
    } else {
      isLeap = true;
      --i;
      --monCyl;
    }
  }

  // offset小于0时，也要校正
  if (offset < 0) {
    offset += temp;
    --i;
    --monCyl;
  }

  month = i;
  day = offset + 1;

  return { year, month, day, leap, isLeap, yearCyl, monCyl, dayCyl, hourCyl };
}

function toStr(year: number, month: number, day: number, isLeap: boolean) {
  return (
    year +
    '年' +
    (isLeap ? '闰' : '') +
    chineseNumber[month - 1] +
    '月' +
    getChinaDay(day) +
    ' ' +
    cyclicalm(yearCyl) +
    '年' +
    cyclicalm(monCyl) +
    '月' +
    cyclicalm(dayCyl) +
    '日' +
    cyclicalm(hourCyl) +
    '时辰'
  );
}

// 记录公历和农历某天的日期
function calElement(
  sYear: number,
  sMonth: number,
  sDay: number,
  week: string,
  lYear: number,
  lMonth: number,
  lDay: number,
  isLeap: boolean,
) {
  return {
    isToday: false,
    // 公历
    sYear: sYear,
    sMonth: sMonth,
    sDay: sDay,
    week: week,

    // 农历
    lYear: lYear,
    lMonth: lMonth,
    lDay: lDay,
    isLeap: isLeap,

    // 节日记录
    // 农历节日
    lunarFestival: '',

    // 公历节日
    solarFestival: '',

    // 节气
    solarTerms: '',
  };
}

// 保存y年m+1月的相关信息
let mat = 9;
let fat = mat;

var eve = 0;

function calendar(y: number, m: number) {
  fat = mat = 0;

  var sDObj,
    lDObj,
    lY,
    lM,
    lD = 1,
    lL,
    lX = 0,
    tmp1,
    tmp2;

  var lDPOS = new Array(3);

  var n = 0;

  var firstLM = 0;

  sDObj = new Date(y, m, 1); // 当月第一天的日期
  const length = solarDays(y, m); // 公历当月天数
  const firstWeek = sDObj.getDay(); // 公历当月1日星期几
  if (m + 1 == 5) {
    fat = sDObj.getDay();
  }

  if (m + 1 == 6) {
    mat = sDObj.getDay();
  }

  for (let i = 0; i < length; i++) {
    if (lD > lX) {
      sDObj = new Date(y, m, i + 1); // 当月第一天的日期
      lDObj = Dianaday(sDObj); // 农历

      lY = lDObj.year; // 农历年

      lM = lDObj.month; // 农历月

      lD = lDObj.day; // 农历日
      lL = lDObj.isLeap; // 农历是否闰月

      lX = lL ? leapDays(lY) : monthDays(lY, lM); // 农历当月最後一天

      if (lM == 12) {
        eve = lX;
      }

      if (n == 0) {
        firstLM = lM;
      }

      lDPOS[n++] = i - lD + 1;
    }

    this[i] = calElement(
      y,
      m + 1,
      i + 1,
      chineseNumber[(i + this.firstWeek) % 7],
      lY,
      lM,
      lD++,
      lL,
    );

    if ((i + firstWeek) % 7 == 0) {
      this[i].color = 'red'; // 周日颜色
    }
  }

  // 节气

  tmp1 = sTerm(y, m * 2) - 1;

  tmp2 = sTerm(y, m * 2 + 1) - 1;

  this[tmp1].solarTerms = solarTerm[m * 2];

  this[tmp2].solarTerms = solarTerm[m * 2 + 1];

  if ((this.firstWeek + 12) % 7 == 5)
    // 黑色星期五

    this[12].solarFestival += '黑色星期五';

  if (y == tY && m == tM) {
    // 今日
    this[tD - 1].isToday = true;
  }
}

var cld;

function drawCld(SY: number, SM: number) {
  var TF = true;

  var p1 = (p2 = '');

  var i, sD, s, size;

  cld = calendar(SY, SM);

  // 生肖
  GZ.innerHTML =
    '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;【' +
    animals[(SY - 4) % 12] +
    '】';
  for (i = 0; i < 42; i++) {
    sObj = eval('SD' + i);

    lObj = eval('LD' + i);

    sObj.className = '';

    sD = i - cld.firstWeek;

    if (sD > -1 && sD < cld.length) {
      // 日期内

      sObj.innerHTML = sD + 1;

      // 今日颜色
      if (cld[sD].isToday) {
        sObj.style.color = '#9900FF';
      } else {
        sObj.style.color = '';
      }

      if (cld[sD].lDay == 1) {
        // 显示农历月

        lObj.innerHTML =
          '<b>' +
          (cld[sD].isLeap ? '闰' : '') +
          cld[sD].lMonth +
          '月' +
          (monthDays(cld[sD].lYear, cld[sD].lMonth) == 29 ? '小' : '大') +
          '</b>';
      } else {
        lObj.innerHTML = getChinaDay(cld[sD].lDay);
      } // 显示农历日
      var Slfw = (Ssfw = null);

      s = cld[sD].solarFestival;

      for (var ipp = 0; ipp < lunarFestival.length; ipp++) {
        // 农历节日

        if (parseInt(lunarFestival[ipp].substr(0, 2)) == cld[sD].lMonth) {
          if (parseInt(lunarFestival[ipp].substr(2, 4)) == cld[sD].lDay) {
            lObj.innerHTML = lunarFestival[ipp].substr(5);

            Slfw = lunarFestival[ipp].substr(5);
          }
        }

        if (12 == cld[sD].lMonth) {
          // 判断是否为除夕

          if (eve == cld[sD].lDay) {
            lObj.innerHTML = '除夕';
            Slfw = '除夕';
          }
        }
      }

      for (var ipp = 0; ipp < solarFestival.length; ipp++) {
        // 公历节日

        if (parseInt(solarFestival[ipp].substr(0, 2)) == SM + 1) {
          if (parseInt(solarFestival[ipp].substr(2, 4)) == sD + 1) {
            lObj.innerHTML = solarFestival[ipp].substr(5);

            Ssfw = solarFestival[ipp].substr(5);
          }
        }
      }

      if (SM + 1 == 5) {
        // 母亲节

        if (fat == 0) {
          if (sD + 1 == 7) {
            Ssfw = '母亲节';
            lObj.innerHTML = '母亲节';
          }
        } else if (fat < 9) {
          if (sD + 1 == 7 - fat + 8) {
            Ssfw = '母亲节';
            lObj.innerHTML = '母亲节';
          }
        }
      }

      if (SM + 1 == 6) {
        // 父亲节

        if (mat == 0) {
          if (sD + 1 == 14) {
            Ssfw = '父亲节';
            lObj.innerHTML = '父亲节';
          }
        } else if (mat < 9) {
          if (sD + 1 == 7 - mat + 15) {
            Ssfw = '父亲节';
            lObj.innerHTML = '父亲节';
          }
        }
      }

      if (s.length <= 0) {
        // 设置节气的颜色

        s = cld[sD].solarTerms;

        if (s.length) {
          s = s.fontcolor('limegreen');
        }
      }

      if (s.length) {
        lObj.innerHTML = s;
        Slfw = s;
      } // 节气
      if (Slfw != null && Ssfw != null) {
        lObj.innerHTML = Slfw + '/' + Ssfw;
      }
    } else {
      // 非日期

      sObj.innerHTML = '';

      lObj.innerHTML = '';
    }
  }
}

// 在下拉列表中选择年月时,调用自定义函数drawCld(),显示公历和农历的相关信息

function changeCld() {
  var y, m;

  y = CLD.SY.selectedIndex + 1900;

  m = CLD.SM.selectedIndex;

  drawCld(y, m);
}

// 用自定义变量保存当前系统中的年月日

var Today = new Date();

var tY = Today.getFullYear();

var tM = Today.getMonth();

var tD = Today.getDate();

// 打开页时,在下拉列表中显示当前年月,并调用自定义函数drawCld(),显示公历和农历的相关信息

function initial() {
  CLD.SY.selectedIndex = tY - 1900;

  CLD.SM.selectedIndex = tM;

  drawCld(tY, tM);
}

export default {};
